<!--

    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.

-->

<html><head>
<title>Datasystems API</title>
<link rel="stylesheet" href="../../../../prose.css" type="text/css">
</head><body>

<p class="overviewlink"><a href="../../../../overview-summary.html">Overview</a></p>

<h1>Javadoc</h1>

There are three packages in this API:

<ul>

<li><a href="../package-summary.html"><code>org.openide.loaders</code></a>

handles the association of files together into groups and assigning
types to data.

<li><a href="@org-openide-nodes@/org/openide/cookies/package-summary.html"><code>org.openide.cookies</code></a>

provides a design pattern for attachable behaviors for data objects and nodes.

<li><a href="@org-openide-util-ui@/org/openide/util/datatransfer/package-summary.html"><code>org.openide.util.datatransfer</code></a>

implements some extensions to the clipboard.

</ul>

<h1>Contents</h1>

<ul>

<li><a href="#loader-do">Loaders and Data Objects</a>
<ul>
<li><a href="#intro-loader">What is a loader used for?</a>
<li><a href="#multi">Multiple-file loaders</a>
<li><a href="#single">Single-file loaders</a>
<li><a href="#entry">Entries</a>
<li><a href="#do-get">Getting a data object</a>
<li><a href="#delegate">Node Delegates</a>
<li><a href="#write-loader">Writing a loader and data object</a>
<li><a href="#sys-loaders">System loaders</a>
</ul>

<li><a href="#cookie">Cookies</a>
<ul>
<li><a href="#intro-cookie">What is a cookie?</a>
<li><a href="#std-cookie">Standard cookies and supports</a>
<li><a href="#write-cookie">Writing a cookie</a>
<li><a href="#write-support">Writing a support for an existing cookie</a>
<li><a href="#use-support">Using an existing support</a>
</ul>

<li><a href="#clipboard">Extended Clipboard</a>
<ul>
<li><a href="#convertor">Convertors</a>
<li><a href="#clipboard-ev">Event notification</a>
<li><a href="#multi-transfer">Multi-transfers</a>
</ul>

<li><a href="#diagrams">UML diagrams</a>
<ul>
<li><a href="#diagram_data_objects">Data objects class diagram</a>
<li><a href="#diagram_data_loaders">Data loaders class diagram</a>
</ul>


</ul>

<h1>Datasystems API</h1>

<h2><a name="loader-do">Loaders and Data Objects</a></h2>

<div class="nonnormative">

There are a few related object types used in NetBeans to handle
creation of structured, high-level data based on files found on a

<a href="@org-openide-filesystems@/org/openide/filesystems/FileSystem.html">filesystem</a>.

In summary, the system

<a href="../DataLoaderPool.html">loader pool</a>

is responsible for scanning files in a directory on disk, weeding out
irrelevant files of no interest, and grouping the rest into
logical chunks, or just determining what type of data each represents.
It does this scanning by asking each registered

<a href="../DataLoader.html">data loader</a>

whether or not the given file(s) should be handled. The first loader
to recognize a file takes ownership of it, and creates a matching

<a href="../DataObject.html">data object</a>

to represent it to the rest of NetBeans.

<h3><a name="intro-loader">What is a loader used for?</a></h3>

There are a few reasons why loaders are used in NetBeans, rather than
just accessing raw files (and perhaps typing them by extension or MIME
type):

<ul>

<li>Most importantly, it is possible to group a cluster of files
together. For example, the NetBeans Form Editor module recognizes a
special cluster pattern:

<pre>
myform.java
myform.form
myform.class
myform$1.class
myform$2.class
</pre>

All of these files are handled by NetBeans as a single data object
with a single set of actions applicable to it. In the Explorer, only
one master node is created for this data object (though it has some
substructure) - the user does not see these files as isolated.

<li>Irrelevant files, such as backup files, test output, etc. do not
clutter up the displayed Filesystems, since no loader accepts them - so
no node is created for them in the Explorer.

<li>A data object holds a number of behaviors that a bare file object
does not. For example, it can hold <a href="#cookie">cookies</a>
providing various behaviors; have an associated opened editor; can be
specified as a template; may provide special procedures to be run when
it is moved or renamed; etc.

<li>Special pseudo-files, such as

<a href="../DataShadow.html"><code>DataShadow</code></a>s,

are interpreted using Datasystems, not Filesystems.

</ul>

</div>

<h3><a name="multi">Multiple-file loaders</a></h3>

These typically subclass

<a href="../MultiFileLoader.html"><code>MultiFileLoader</code></a>.

Like the loader used by the Form Editor, they are able to recognize
multiple files at once and create a data object from them. All data
objects have a

<a href="../DataObject.html#getPrimaryFile--">primary file</a>

which is representative of the data object;
e.g. <code>myform.java</code> in the previous example. As well, these
multi loaders may have any number of

<a href="../DataObject.html#files--">secondary files</a>.

<p>The basic mechanism a multi-file loader uses, is that the loader
pool will pass it file objects to recognize in an arbitrary order; the
loader may get a primary or secondary file first. Either way, it must
recognize that it belongs to a cluster; find the primary file if it
got a secondary one; and create a new

<a href="../MultiDataObject.html"><code>MultiDataObject</code></a>

containing the supplied file as an

<a href="../MultiDataObject.Entry.html">entry</a>.

When other files in the cluster are passed to the loader, it must
create new entries in the <em>same</em> multi data object, to indicate
their association.

<h3><a name="single">Single-file loaders</a></h3>

These typically subclass

<a href="../UniFileLoader.html"><code>UniFileLoader</code></a>.

A single-file loader is of course simpler, and is likely to be more
commonly used (since the majority of file types make sense by
themselves). The default implementation makes it straightforward to
create a subclass recognizing only certain file extensions.

<p>This kind of loader may be used for, e.g., HTML files which ought
to be recognized as such and given a simple data object appropriate to
working with HTML (so that opening it by default launches a web
browser, and so on).

<p>Note that the standard <code>UniFileLoader</code> is actually a
special type of <code>MultiFileLoader</code> (only recognizing one
file), so that it actually creates a

<a href="../MultiDataObject.html"><code>MultiDataObject</code></a>

when it recognizes its file. Normally you will use a
<code>UniFileLoader</code> for most purposes, so the behaviors in
<code>MultiDataObject</code> are generally available as defaults. If
you had some reason to avoid using this kind of data object, you could
of course subclass <code>DataLoader</code> and <code>DataObject</code>
directly.

<h3><a name="entry">Entries</a></h3>

Entries represent a single file in a <code>MultiDataObject</code>, and
thus are commonly used in all loaders (even single-file
loaders). Normally

<a href="../MultiDataObject.Entry.html"><code>MultiDataObject.Entry</code></a>

will not be specially subclassed; most module authors will use

<a href="../FileEntry.html"><code>FileEntry</code></a>

(a regular entry) and sometimes

<a href="../FileEntry.Numb.html"><code>FileEntry.Numb</code></a>

(a discardable file which should not be slavishly moved about just
because the primary file is).

<p>Entries primarily handle operations on the whole file, such as
copying or instantiation from template, and provide the ability to
insert special behavior hooks into such operations, if desired. For
example, a Java source entry might want to rename its package and
class name when it was moved. (The easiest way to create "smart"
templates such as this is to make the entry a

<a href="../FileEntry.Format.html"><code>FileEntry.Format</code></a>.)

<h3><a name="do-get">Getting a data object</a></h3>

Normally you do not need to explicitly retrieve a data object - the
loader pool will create them on demand, present them to the user in
the Explorer as nodes, and user actions will trigger use of the data
object. However, if you do need to retrieve the data object for a file
object you may do so using

<a href="../DataObject.html#find-org.openide.filesystems.FileObject-"><code>DataObject.find(...)</code></a>,

which will create a new data object for the file if it needs to,
otherwise will return the existing one. (Catch

<a href="../DataObjectNotFoundException.html"><code>DataObjectNotFoundException</code></a>

in case the file is not recognizable to any loader.)

<h3><a name="delegate">Node Delegates</a></h3>

Data objects have separate, but associated,

<a href="@org-openide-nodes@/org/openide/nodes/Node.html"><code>Node</code></a>s

which represent them in the Explorer and present a meaningful
interface to the user. You may use

<a href="../DataObject.html#getNodeDelegate--"><code>DataObject.getNodeDelegate()</code></a>

to retrieve the node delegate for a data object, if necessary.

<h3><a name="write-loader">Writing a loader and data object</a></h3>

This section is the most important for most people: after a loader has
been correctly written and installed, the system takes care of
providing files for it to recognize; constructing nodes for the files;
etc.; and most further implementation of a module will be callbacks
run in response to some aspect of the objects created here.

<h4>Module installation</h4>
<a name="register"></a>
<p>First of all, you must be able to register your loader in the
module so that NetBeans knows about it. The preferred way since version
7.0 of <code>org.openide.loaders</code> module is to assign the loader
to appropriate MIME type. If the 
<a
    href="@org-openide-filesystems@/org/openide/filesystems/FileObject.html">FileObject</a>
of your interest returns for example <code>text/xml+acme</code> from its
<a
    href="@org-openide-filesystems@/org/openide/filesystems/FileObject.html#getMIMEType--">getMIMEType()</a>
method, then you shall register its 
<a href="../DataLoader.html">DataLoader</a> or other configured 
<a href="../DataObject.Factory.html">DataObject.Factory</a> into layer file
of your module:
<pre>
&lt;folder name="Loaders"&gt;
  &lt;folder name="text"&gt;
    &lt;folder name="xml+acme"&gt;
      &lt;folder name="Factories"&gt;
        &lt;file name="org-acme-pkg-AcmeLoader.instance"&gt;
          &lt;attr name="position" intvalue="100"/&gt;
        &lt;/file&gt;
      &lt;/folder&gt;
    &lt;/folder&gt;
  &lt;/folder&gt;
&lt;/folder&gt;
</pre>
Then the <code>AcmeLoader</code> will be consulted everytime the system needs
to recognize file with <code>text/xml+acme</code> MIME type. Please refer 
to <a href="@org-openide-filesystems@/org/openide/filesystems/doc-files/HOWTO-MIME.html">
separate specification</a>
document on information how to register a MIME type declaratively.
<p>
The recognition process for any file consults loaders registered in an 
old, deprecated style first, then it checks folder
<code>Loaders/mime/type/Factories</code> for all instances of 
<a href="../DataObject.Factory.html">DataObject.Factory</a> which also includes
instances of 
all <a href="../DataLoader.html">DataLoader</a>s. If no appropriate loader
is found, the scan continues among loaders registered as
<code>Loaders/content/unknown/Factories</code>. At the end the recognition
checks standard system loaders. In case of registration of multiple loaders in
one folder you can specify their order by using the 
<a href="@org-openide-modules@/org/openide/modules/doc-files/api.html#how-layer">
position attributes</a>. Pay attention to whether this loader is potentially in conflict
with other existing or probable loaders; if so, you should specify
that it take higher or lower precedence than these others. (This would
be necessary, e.g., if your loader recognized everything that another
loader did, and used that loader, but also added further special
behavior.)

<h4>Deciding what to subclass</h4>

Your first step in writing the loader is deciding what to
subclass. Though you could in principle subclass
<code>DataLoader</code> directly, in practice it is easier and better
to subclass either

<a href="../MultiFileLoader.html"><code>MultiFileLoader</code></a>

or

<a href="../UniFileLoader.html"><code>UniFileLoader</code></a>,

according to whether your loader needs to cluster files, or just needs
to deal with a single primary file.

<h4>Handling file recognition</h4>

For a single-file loader, handling file recognition is quite straightforward from the point of view of the API: you just need to override

<a href="../UniFileLoader.html#findPrimaryFile-org.openide.filesystems.FileObject-"><code>UniFileLoader.findPrimaryFile(...)</code></a>

to return its argument if this file is of the type that should be
handled by your loader, or <code>null</code> if it is not.

<p>In fact, providing that your loader is of the common sort that just
looks for a specific file extension, you do not even need to override
this method at all; simply create an appropriate

<a href="../ExtensionList.html"><code>ExtensionList</code></a>

and call

<a href="../UniFileLoader.html#setExtensions-org.openide.loaders.ExtensionList-"><code>UniFileLoader.setExtensions(...)</code></a>

in your loader's constructor.

<p>For a multi-file loader, the situation is slightly more complex,
but still NetBeans takes care of most of the work for you. You should
implement

<a href="../MultiFileLoader.html#findPrimaryFile-org.openide.filesystems.FileObject-"><code>MultiFileLoader.findPrimaryFile(...)</code></a>

as follows:

<ul>

<li>If the passed-in file object is of the correct type for your
primary file, just return it.

<li>If the passed-in file object is of the correct type for a
secondary file in your loader, you should attempt to find the primary
file which it should be associated with, and return that. For this
purpose, you may find it useful to call

<a
href="@org-openide-filesystems@/org/openide/filesystems/FileUtil.html#findBrother-org.openide.filesystems.FileObject-java.lang.String-"><code>FileUtil.findBrother(...)</code></a>,

or perform a similar lookup by hand.

<li>Otherwise (if the passed-in object could not be either a primary
or secondary file), just return <code>null</code>.

</ul>

You need not worry about which order the primary and secondary files
are recognized in, or whether some other loader may have gotten to a
file first - the implementation in NetBeans takes care of this for you.

<h4>Creating the data object</h4>

The most interesting part of the loader is that which actually creates
the data object from the underlying file object. You must implement

<a href="../MultiFileLoader.html#createMultiObject-org.openide.filesystems.FileObject-"><code>MultiFileLoader.createMultiObject(...)</code></a>

in order to do this. The method will be passed the correct primary
file object for you to work with.

<p>To write the data object, subclass

<a href="../MultiDataObject.html"><code>MultiDataObject</code></a>.

Your constructor will call the superclass constructor (so the loader
will pass in the desired primary object and a reference to
itself). You do <em>not</em> need to worry about whether or not to
throw

<a href="../DataObjectExistsException.html"><code>DataObjectExistsException</code></a>

in the constructor; it will be thrown automatically by the superclass if necessary.

<p>After that, what to override in the data object is up to you. Other
than things mentioned below, you may find it useful to prevent the
data object from being renamed or otherwise tampered with, if doing so
would make it useless or corrupted in some way; just return
<code>false</code> from e.g.

<a href="../MultiDataObject.html#isRenameAllowed--"><code>MultiDataObject.isRenameAllowed()</code></a>.

<p>Or, if e.g. moves are to be permitted but require special
treatment, you may override e.g.

<a href="../MultiDataObject.html#handleMove-org.openide.loaders.DataFolder-"><code>MultiDataObject.handleMove(...)</code></a>.

<h4>Choosing entry types</h4>

For single-file loaders, the default implementation of

<a
href="../UniFileLoader.html#createPrimaryEntry-org.openide.loaders.MultiDataObject-org.openide.filesystems.FileObject-"><code>UniFileLoader.createPrimaryEntry(...)</code></a>

just produces a

<a href="../FileEntry.html"><code>FileEntry</code></a>,

which is most likely what you want.

<p>For multi-file loaders, you must explicitly select the entry types
by implementing

<a
href="../MultiFileLoader.html#createPrimaryEntry-org.openide.loaders.MultiDataObject-org.openide.filesystems.FileObject-"><code>MultiFileLoader.createPrimaryEntry(...)</code></a>

and

<a
href="../MultiFileLoader.html#createSecondaryEntry-org.openide.loaders.MultiDataObject-org.openide.filesystems.FileObject-"><code>MultiFileLoader.createSecondaryEntry(...)</code></a>.

<p>Typically, the primary entry will be a <code>FileEntry</code>, and
will behave normally. The secondary entry might also be a
<code>FileEntry</code>, if it makes sense to move the secondary
entries along with the primary (i.e., if they are valuable enough to
do so, and will not be corrupted); in many cases you will want to use
a

<a href="../FileEntry.Numb.html"><code>FileEntry.Numb</code></a>,

which will not be moved along with the primary file, and may just
be discarded (for example, this would be useful for compiled
<code>*.class</code> files, cached indices, etc.). For such dummy
files, you will generally also want to use

<a href="@org-openide-filesystems@/org/openide/filesystems/FileObject.html#setImportant-boolean-"><code>FileObject.setImportant(...)</code></a>

to prevent the file from being considered by a version control
system, for example.

<p>It is possible to specify custom copy/move/etc. behavior for
individual files in your data object by subclassing

<a href="../MultiDataObject.Entry.html"><code>MultiDataObject.Entry</code></a>

(or <code>FileEntry</code>)
and providing a non-obvious implementation. If you need custom
behavior for the whole data object at once, it is preferable to do so
by overriding methods on the data object, as mentioned above.

<p><a href="../FileEntry.Format.html"><code>FileEntry.Format</code></a>

is a convenient entry type to use if you wish to perform substitution of some type
of token when creating the file from template. Typically the method

<a
href="../FileEntry.Format.html#createFormat-org.openide.filesystems.FileObject-java.lang.String-java.lang.String-"><code>FileEntry.Format.createFormat(...)</code></a>

will be implemented to return an instance of

<a href="@org-openide-util@/org/openide/util/MapFormat.html"><code>MapFormat</code></a>

containing substitution keys and values according to the name and package of the file object;
constants used by the module; values of associated system options; the current time and
date or user name; etc. For example, the Java data loader uses this entry type with a customized
<code>MapFormat</code> permitting it to replace keys such as <code>__NAME__</code> with the
(new) name of the class, or <code>__USER__</code> with the current user name (as taken from a
system option, defaulted from the Java system property).

<h4>Loader state and bean info</h4>

Data loaders all implicitly extend

<a href="@org-openide-util-ui@/org/openide/util/SharedClassObject.html"><code>SharedClassObject</code></a>,

which means that there is only intended to be a single instance of the loader
per class, and all associated configuration and properties are stored in a shared
state pool. <code>SharedClassObject</code> manages this state implicitly; if you
wish to associate any properties with a data loader, you should:

<ol>

<li> Implement getter and setter methods to call

<a href="@org-openide-util-ui@/org/openide/util/SharedClassObject.html#getProperty-java.lang.Object-"><code>SharedClassObject.getProperty(key)</code></a>

and

<a href="@org-openide-util-ui@/org/openide/util/SharedClassObject.html#putProperty-java.lang.String-java.lang.Object-boolean-"><code>SharedClassObject.putProperty(key, value, true)</code></a>

(the latter will automatically fire property changes and synchronize for you).

<li> Override <code>readExternal</code> and <code>writeExternal</code> to read and write
your property values from the stream. Please always first call the super methods.

</ol>

<p>You should use the method

<a href="@org-openide-util-ui@/org/openide/util/SharedClassObject.html#initialize--"><code>SharedClassObject.initialize()</code></a>

to set up the shared instance, including both your own properties, and standard ones such as

<a href="../DataLoader.html#setDisplayName-java.lang.String-"><code>DataLoader.setDisplayName(String)</code></a>,

<a href="../DataLoader.html#setActions-org.openide.util.actions.SystemAction:A-"><code>DataLoader.setActions(SystemAction[])</code></a>,

and

<a href="../UniFileLoader.html#setExtensions-org.openide.loaders.ExtensionList-"><code>UniFileLoader.setExtensions(ExtensionList)</code></a>.

<p>Finally, data loaders will be customized by the user as Beans (and persisted using
externalization). For this reason, they should have an associated bean info class
which should typically specify:

<ol>

<li> A list of additional bean infos to retrieve (introspect on the superclass).

<li> Display names and hints (and property editors, etc.) for all properties you define.

<li> An icon.

</ol>

<h4>Providing cookies and actions</h4>

The most common way in which a new data object type will present its
useful features to NetBeans is by adding cookies and actions specific
to it. Please see the <a href="#cookie">cookie subsection</a> of this
document for information on cookies, and the

<a href="@org-openide-actions@/org/openide/actions/doc-files/api.html">Actions API</a>

for details on how to write actions.

<p>One simple way to add cookie support to a data object is simply to
implement the cookie's interface on the data object itself; then it
will automatically support the cookie. But doing so for many cookies
may be a bad idea, as your data object class will become cluttered;
and there is no way to alter the set of cookies provided in this way.

<p>A better technique is to provide cookies explicitly from

<a href="../DataObject.html#getCookie-java.lang.Class-"><code>DataObject.getCookie(...)</code></a>.

Assuming that you are subclassing <code>MultiDataObject</code>, you
need not override this method yourself, but rather should use

<a href="../MultiDataObject.html#getCookieSet--"><code>MultiDataObject.getCookieSet()</code></a>

in the constructor and add the cookies you
want to provide by default. Then it is possible to extend this set
later, and to more easily examine its contents.

<p>You may attach some

<a href="@org-openide-util-ui@/org/openide/util/actions/SystemAction.html">actions</a>

to the nodes <a href="#create-delegate">associated</a> with your data
objects. The easiest way to do this is to call

<a href="../DataLoader.html#setActions-org.openide.util.actions.SystemAction:A-"><code>DataLoader.setActions(...)</code></a>

in your loader's

<a href="@org-openide-util-ui@/org/openide/util/SharedClassObject.html#initialize--"><code>SharedClassObject.initialize()</code></a>

method, which lets you provide a set of
actions appropriate to all data objects created by this
loader. Please see the <a
href="@org-openide-actions@/org/openide/actions/doc-files/api.html#attach">Actions API</a> for
an example displaying suggested standard actions to include, and
their positioning.

<p>Or, you may wish to selectively attach actions to certain data
objects' nodes and not others. If you need to do this, please override

<a href="../DataNode.html#getActions-boolean-"><code>DataNode.getActions(boolean)</code></a>

when creating your node delegate; you probably want to call the super
method and append any additional actions this particular node should
have.

<p>The nodes ought also to have a default action, which will be
performed in response to a generic user-initiated event, such as a
double-click on the node; this should do something safe and obvious on
the node, such as opening it for editing, running it if executable,
etc. To do so, your node delegate should override

<a href="../DataNode.html#getPreferredAction--"><code>DataNode.getPreferredAction()</code></a>.

If unspecified, NetBeans may still provide a generic default action,
such as displaying properties of the object.

<p>The default implementation is only specified in the case of
templates, so you may override this. However, if there is a chance
this data object might serve as a template, for UI consistency this
default action should be preserved; you may check

<a href="../DataObject.html#isTemplate--"><code>DataObject.isTemplate()</code></a>,

and if true, provide

<a href="../../actions/InstantiateAction.html"><code>InstantiateAction</code></a>

as the result.

<h4><a name="create-delegate">Creating a node delegate</a></h4>

You must create a

<a href="@org-openide-nodes@/org/openide/nodes/Node.html"><code>Node</code></a>

to represent your data object in the Explorer hierarchy, so that the
user may interact with it visually. The method

<a href="../DataObject.html#createNodeDelegate--"><code>DataObject.createNodeDelegate()</code></a>

controls what sort of node should be created. To control the icon, you
should use

<a href="@org-openide-nodes@/org/openide/nodes/AbstractNode.html#setIconBaseWithExtension-java.lang.String-"><code>AbstractNode.setIconBaseWithExtension(...)</code></a>

on the newly created <code>DataNode</code>, either in its constructor
(if subclassing) or in <code>DataObject.createNodeDelegate()</code>.

<p>You have considerable latitude in creating this node; e.g. the Form
Editor actually creates a full hierarchy for nodes representing forms,
including one subtree representing the Java class object (and its
various members), as well as a subtree representing the component
structure of the form (as displayed in the Component Inspector).

<p>For simple loaders, it is not typically necessary to create a
special node subclass for the delegate, as you may provide an icon,
cookies, and common actions without doing so.

<h3><a name="sys-loaders">System loaders</a></h3>

NetBeans installs a few extra "hidden" loaders into the loader pool, as
are returned by

<a href="../DataLoaderPool.html#allLoaders--"><code>DataLoaderPool.allLoaders()</code></a>.

Currently, these include among other things:

<ul>

<li>A folder loader, which only recognizes file folders and creates a

<a href="../DataFolder.html"><code>DataFolder</code></a>

for them. This folder will have a few standard system actions
associated with its

<a href="../DataFolder.FolderNode.html">node</a>,

can be sorted, etc.

<li>A shadow loader, which recognizes files with a magic extension,
and treats them similarly to symbolic links. The created data object
is a

<a href="../DataShadow.html"><code>DataShadow</code></a>,

and generally behaves just like the object it points to.

<li>Support for

<a href="../XMLDataObject.html">XML files</a>.

</ul>

<!-- XXX no longer true probably
These system loaders always come first in the loader pool, so normally
they take precedence over module-installed loaders. However, if it is
necessary to override their behavior, it is possible for a data loader
to

<a href="../DataLoader.html#markFile(org.openide.filesystems.FileObject)">mark</a>

a file (e.g. a file folder or shadow file) as having the given loader
as its preferred loader, so that this loader will be given a first
shot at recognizing it. This is done using a special

<a href="@org-openide-filesystems@/org/openide/filesystems/FileObject.html#getAttributes()">file attribute</a>.
-->

<!-- XXX race condition, bad workaround
<p>Overriding a system loader is not very useful if the file might
have already been recognized by a system loader, which could be the
case if it was scanned for a data object before the custom loader got
to it (and this is difficult to predict); so this would better be done
upon

<a href="@org-openide-filesystems@/org/openide/filesystems/FileObject.html#getChildren()">creation</a>

of the file object by the underlying filesystem (which would need to
cooperate with the loader in this regard).
-->


<h2><a name="cookie">Cookies</a></h2>

<!-- XXX this ss should maybe be in Services/Lookup API -->

Cookies provide a way for both data objects and nodes to indicate to
NetBeans in a flexible fashion what types of (usually user-initiated)
operations they are capable of supporting, and even to dynamically add
and remove these capabilities.

<h3><a name="intro-cookie">What is a cookie?</a></h3>

A <em>cookie</em> is a design pattern used to separate the
presentation of implementation of some interface from the actual
object that implementation ought to be associated with. As such, it is
a convenient way of removing the requirement that all interfaces
presented by the cookie holder (either a data object or

<a href="@org-openide-nodes@/org/openide/nodes/Node.html">node</a>)

be actually implemented by the primary Java class of the object. If
desired, the primary Java class can in fact be the cookie implementor,
though this is a special case - some holder objects just declare
themselves by default to hold all cookies their own class implements.

<p><em>Take care</em> not to confuse this NetBeans usage of the word
with a different meaning sometimes used in computer science, that of
an opaque callback object.

<p>Originally there used to be a marker interface
<a href="@org-openide-nodes@/org/openide/nodes/Node.Cookie.html"><code>Node.Cookie</code></a>,
however it is no longer necessary to use it. Rather rely on
<a href="@org-openide-nodes@/org/openide/nodes/Node.html#getLookup--">getLookup</a>
method which can deal with plain Java objects.

As such there are no requirements as to what makes a valid
cookie - typically it will provide a small set of abstract operations,
such as "opening", "compiling", "searching", etc.

<p>Uses of cookies on nodes are not much different from uses on data
objects; the initial cookie detection is done by

<a href="@org-openide-nodes@/org/openide/nodes/Node.html#getLookup--"><code>Node.getLookup().lookup(...)</code></a>;

however the default data node provides

<a href="../DataNode.html"><code>DataNode.getLookup(...)</code></a>

that looks inside 

<a href="../MultiDataObject.html#getCookieSet--"><code>MultiDataObject.getCookieSet()</code></a>.

<h4><a name="attach-retrieve">Attaching and retrieving cookies</a></h4>

<p>In short, there are a number of ways to attach cookies to either a
node or data object (and you may listen for changes in the set of
supported cookies, etc.). In all cases, the
<a href="@org-openide-util-lookup@/org/openide/util/Lookup.html#lookup-java.lang.Class-">lookup(Class)</a>
method
is used by the system to
determine whether or not a given cookie is supported: thus, cookies
are identified by their <em>representation class</em>, i.e. the Java
class of the cookie interface. The system will expect to find a cookie
object assignable to that representation class, and this object will
have methods invoked on it to perform the proper action; it is the
responsibility of that cookie object to associate itself to whatever
node or data object is holding it.

<p>Using

<a href="@org-openide-nodes@/org/openide/nodes/CookieSet.html">cookie sets</a>,

it is possible to dynamically add and remove cookies from a
holder (possible
using <a href="@org-openide-util-lookup@/org/openide/util/lookup/AbstractLookup.html">AbstractLookup</a>).
This is appropriate for cookie types whose applicability may
vary over time. For example, some objects may be compilable at certain
times, but if they have been compiled recently and are already
up-to-date, this support should be temporarily disabled. In the common
case that an action (say, in the system Build menu for Compile) is
sensitive to the cookie provided by the currently selected object (in
this case the compilation cookie), this menu item can be automatically
grayed out when necessary; and then reenabled when either the
selection changes, or the object changes state so as to make the
cookie appropriate once more, at which time the folder re-adds the
cookie to its cookie set and
<a href="@org-openide-util-lookup@/org/openide/util/LookupListener.html">LookupListener</a>
may observer the
<a href="@org-openide-nodes@/org/openide/nodes/Node.html#fireCookieChange--">fired changes</a>
to this effect.

<h4>Cookie Usage Scenarios</h4>

<p>There are various scenarios for ways in which you can use cookies,
which demonstrate their flexibility. In the examples that follow,
<code>C</code> means a cookie interface (or abstract class),
<code>O</code> means a cookie holder (such as <code>Node</code> or
<code>DataObject</code>), and <code>S</code> means a cookie support
(concrete implementation). For example, signatures might look like
this:</p>

<pre>
<font class="keyword">public</font> <font class="keyword">interface</font> C {
    <font class="type">void</font> foo();
}
<font class="keyword">public</font> <font class="keyword">class</font> S <font class="keyword">implements</font> C {
    <font class="keyword">private</font> <font class="type">String</font> param;
    <font class="keyword">public</font> S(<font class="type">String</font> param) {
        <font class="keyword">this</font>.param = param;
    }
    <font class="keyword">public</font> <font class="type">void</font> foo() {
        System.out.println(<font class="string">"foo: "</font> + param);
    }
}
<font class="keyword">public</font> <font class="keyword">class</font> O <font class="keyword">extends</font> <font class="type">DataObject</font> {<font class="comment">/* ... */</font>}
</pre>


<dl>

<dt>Basic usage</dt>

<dd><p>Using cookies in the common way is pretty easy.</p>

<pre>
<font class="keyword">public</font> <font class="keyword">class</font> O <font class="keyword">extends</font> <font class="type">DataObject</font> {
    <font class="keyword">public</font> O(<font class="type">FileObject</font> fo) {
        <font class="comment">// super...
</font>        getCookieSet().assign(C1.class, <font class="keyword">new</font> S1(fo));
        getCookieSet().assign(C2.class, <font class="keyword">new</font> S2(<font class="keyword">this</font>));
    }
}
<font class="keyword">public</font> <font class="keyword">class</font> S1 <font class="keyword">implements</font> C1 {<font class="comment">/* ... */</font>}
<font class="keyword">public</font> <font class="keyword">class</font> S2 <font class="keyword">implements</font> C2 {<font class="comment">/* ... */</font>}
<font class="comment">// ...
</font><font class="type">DataObject</font> o = DataObject.find(someFileObject);
<font class="comment">// o instanceof O, in fact
</font>C1 c1 = o.getLookup().lookup(C1.<font class="keyword">class</font>);
<font class="comment">// c1 instanceof S1
</font><font class="keyword">if</font> (c1 != <font class="constant">null</font>) {
    c1.foo();
}
</pre>

</dd>

<dt>Multiple inheritance</dt>

<dd><p>Since cookies do not require language-level multiple
inheritance, you can use subclassing naturally on supports.</p>

<pre>
<font class="keyword">public</font> <font class="keyword">class</font> S1 <font class="keyword">implements</font> C1 {
    <font class="keyword">private</font> <font class="type">String</font> param;
    <font class="keyword">public</font> S1(<font class="type">String</font> param) {
        <font class="keyword">this</font>.param = param;
    }
    <font class="keyword">public</font> <font class="type">void</font> foo1() {
        System.out.println(<font class="string">"foo: "</font> + transform(param));
    }
    <font class="comment">/** Subclasses may customize. */</font>
    <font class="keyword">protected</font> <font class="type">String</font> transform(<font class="type">String</font> in) {
        <font class="keyword">return</font> in;
    }
}
<font class="keyword">public</font> <font class="keyword">abstract</font> <font class="keyword">class</font> S2 <font class="keyword">implements</font> C2 {
    <font class="keyword">private</font> <font class="type">String</font> param;
    <font class="keyword">public</font> S2(<font class="type">String</font> param) {
        <font class="keyword">this</font>.param = param;
    }
    <font class="keyword">public</font> <font class="type">void</font> foo2() {
        <font class="keyword">if</font> (active()) {
            System.out.println(<font class="string">"foo: "</font> + param);
        }
    }
    <font class="comment">/** Subclasses must implement. */</font>
    <font class="keyword">protected</font> <font class="keyword">abstract</font> <font class="type">boolean</font> active();
}
<font class="keyword">public</font> <font class="keyword">class</font> O {
    <font class="keyword">private</font> <font class="type">int</font> state;
    <font class="keyword">public</font> O(<font class="type">String</font> p) {
        state = INACTIVE; <font class="comment">// initially
</font>        getCookieSet().assign(C1.class, <font class="keyword">new</font> <font class="type">MyS1</font>(p));
        getCookieSet().assign(C2.class, <font class="keyword">new</font> <font class="type">MyS2</font>(p));
    }
    <font class="keyword">private</font> <font class="keyword">static</font> <font class="keyword">final</font> <font class="keyword">class</font> <font class="type">MyS1</font> <font class="keyword">extends</font> S1 {
        <font class="keyword">public</font> <font class="type">MyS1</font>(<font class="type">String</font> p) {<font class="keyword">super</font>(p);}
        <font class="keyword">protected</font> <font class="type">String</font> transform(<font class="type">String</font> in) {
            <font class="keyword">return</font> in.toLowerCase();
        }
    }
    <font class="keyword">private</font> <font class="keyword">final</font> <font class="keyword">class</font> <font class="type">MyS2</font> <font class="keyword">extends</font> S2 {
        <font class="keyword">public</font> <font class="type">MyS2</font>(<font class="type">String</font> p) {<font class="keyword">super</font>(p);}
        <font class="keyword">protected</font> <font class="type">boolean</font> active() {
            <font class="keyword">return</font> O.<font class="keyword">this</font>.state == ACTIVE;
        }
    }
}
<font class="comment">// ...
</font>O o = <font class="keyword">new</font> O(<font class="string">"Hello"</font>);
C1 c1 = o.getLookup().lookup(C1.<font class="keyword">class</font>);
<font class="keyword">if</font> (c1 != <font class="constant">null</font>) c1.foo1();
<font class="comment">// prints "foo: hello"
</font>C2 c2 = o.getLookup().lookup(C2.<font class="keyword">class</font>);
<font class="keyword">if</font> (c2 != <font class="constant">null</font>) c2.foo2();
<font class="comment">// does nothing: o is not yet active
</font></pre>

</dd>

<dt>Dynamically add or remove a cookie</dt>

<dd><p>Sometimes you want to change the capabilities of an object
after its creation.</p>

<pre>
<font class="keyword">public</font> <font class="keyword">class</font> <font class="type">O</font> {
    <font class="keyword">private</font> <font class="type">boolean</font> <font class="variable-name">modified</font>;
    <font class="keyword">public</font> <font class="function-name">O</font>(<font class="type">String</font> <font class="variable-name">param</font>) {
        modified = <font class="constant">false</font>;
        <font class="comment">// ...
</font>    }
    <font class="keyword">private</font> <font class="keyword">synchronized</font> <font class="type">void</font> <font class="function-name">markModified</font>() {
        <font class="keyword">if</font> (!modified) {
            <font class="comment">// Newly modified, make it possible to save.
</font>            <font class="comment">// Note this will automatically fire a cookie change.
</font>            getCookieSet().assign(SaveCookie.class, <font class="keyword">new</font> <font class="type">SaveCookie</font>() {
                <font class="keyword">public</font> <font class="type">void</font> <font class="function-name">save</font>() {
                    doSave();
                }
            });
            modified = <font class="constant">true</font>;
        }
    }
    <font class="keyword">private</font> <font class="keyword">synchronized</font> <font class="type">void</font> <font class="function-name">doSave</font>() {
        <font class="keyword">if</font> (modified) {
            <font class="comment">// actually save...then:
</font>            
            getCookieSet().assign(SaveCookie.class);
            modified = <font class="constant">false</font>;
        }
    }
}
</pre>

</dd>


</dl>

</div>

<h3><a name="std-cookie">Standard cookies and supports</a></h3>

Most standard cookies you would want to use exist in the

<a href="@org-openide-nodes@/org/openide/cookies/package-summary.html"><code>org.openide.cookies</code></a>

package. Many of these have standard supports as well, frequently in

<a href="../package-summary.html"><code>org.openide.loaders</code></a>.

Using the Javadoc, the surest way to find cookies and supports is to
look at

<a href="@org-openide-nodes@/org/openide/nodes/Node.Cookie.html"><code>Node.Cookie</code></a>

and browse the subinterfaces; for any cookie of interest, just look
for implementing classes, which are usually supports. (A few cookie
implementations are not of general utility, and so are not documented
as being supports.) The standard supports generally take a

<a href="../MultiDataObject.Entry.html">file entry</a>

in their constructor, as they are designed for use by loaders
attaching them to data objects.

<p>Sometimes a cookie support that is applicable to multiple cookies
may not implement any of them, leaving the choice of which to declare
implementation of, to a subclass. This is the case with the abstract

<a href="../OpenSupport.html"><code>OpenSupport</code></a>,

which actually may be used for any or all of

<a href="@org-openide-nodes@/org/openide/cookies/OpenCookie.html"><code>OpenCookie</code></a>,

<a href="@org-openide-nodes@/org/openide/cookies/ViewCookie.html"><code>ViewCookie</code></a>,

or

<a href="@org-openide-nodes@/org/openide/cookies/CloseCookie.html"><code>CloseCookie</code></a>,

according to the needs of its subclass and holders.

<a href="../../text/EditorSupport.html"><code>EditorSupport</code></a>,

for instance, uses only <code>OpenCookie</code> and
<code>CloseCookie</code>.

<h3><a name="write-cookie">Writing a cookie</a></h3>

Writing a new cookie requires no special knowledge - just extend create
an interface and add its methods according to whatever you need done.

<p>Often, in conjunction with writing a cookie you may want to create
an action which is <a href="#attach-retrieve">sensitive</a> to that
cookie. Then this action may be installed globally in the system (for
example, in a menu bar, on a shortcut, etc.), and only activated when
the current selection provides the cookie.</p>

<div class="nonnormative">

<h3><a name="write-support">Writing a support for an existing cookie</a></h3>

Writing a support also does not require anything non-apparent. It should
be a concrete class, its name conventionally ending in
<code>Support</code>, implementing the cookie interface. Normally it
should have one constructor, taking a

<a href="../MultiDataObject.Entry.html"><code>MultiDataObject.Entry</code></a>

as principal argument, so as to encourage its use in the context of a
loader; the file entry of course gives easy access to the file object
it represents, as well as the data object via

<a href="../MultiDataObject.Entry.html#getDataObject--"><code>MultiDataObject.Entry.getDataObject()</code></a>.

<p>If the support is designed to be usable from someone else's loader,
and it is not obvious for which data objects using the support is
possible, you may be well advised to include a public, static tester
method in the support class indicating whether it would function
correctly with a given file entry/data object. This way, an
independently written loader could easily add the cookie with your
support to any data object it had, without knowing the details of its
prerequisites.

</div>

<h3><a name="use-support">Using an existing support</a></h3>

Using an existing support is generally straightforward - assuming your
data object is a subclass of <code>MultiDataObject</code>, you may
just add a new instance of the support using

<a href="../MultiDataObject.html#setCookieSet-org.openide.nodes.CookieSet-"><code>MultiDataObject.setCookieSet(...)</code></a>

in the constructor, passing in the primary entry (most likely) from

<a href="../MultiDataObject.html#getPrimaryEntry--"><code>MultiDataObject.getPrimaryEntry()</code></a>.



<h2><a name="clipboard">Extended Clipboard</a></h2>

NetBeans implements an extended clipboard, which enhances the functions
provided in the

<a href="@JDK@/java/awt/datatransfer/package-summary.html"><code>java.awt.datatransfer</code></a>

package. This implementation is to be found in

<a href="@org-openide-util-ui@/org/openide/util/datatransfer/package-summary.html"><code>org.openide.util.datatransfer</code></a>.

<p>Enabling complex customizations on both sides of a cut/copy-paste
can be confusing; the

<a href="@org-openide-nodes@/org/openide/nodes/doc-files/api.html#edit">Nodes API</a>

contains a detailed description of these operations as they pertain to
nodes, which may be helpful.

<h3><a name="convertor">Convertors</a></h3>

The extended clipboard,

<a href="@org-openide-util-ui@/org/openide/util/datatransfer/ExClipboard.html"><code>ExClipboard</code></a>,

provides the ability for a prebuilt transferable to support additional
data flavors that it was not originally designed for; then the
convertor supplies the implementation of these conversions.

<p>To write a convertor, just implement

<a href="@org-openide-util-ui@/org/openide/util/datatransfer/ExClipboard.Convertor.html"><code>ExClipboard.Convertor</code></a>.

The Javadoc should provide sufficient information on its sole
method. Installing the convertor is easy; you can just add an instance
of it to

<a href="@org-openide-util-ui@/org/openide/util/doc-files/api.html#instance-folders">lookup</a>.

<h3><a name="clipboard-ev">Event notification</a></h3>

The extended clipboard supports Java Event-based notification of
changes in the contents of the clipboard. Just register your listener
with

<a href="@org-openide-util-ui@/org/openide/util/datatransfer/ExClipboard.html#addClipboardListener-org.openide.util.datatransfer.ClipboardListener-"><code>ExClipboard.addClipboardListener(...)</code></a>.

<h3><a name="multi-transfer">Multi-transfers</a></h3>

<a href="@org-openide-util-ui@/org/openide/util/datatransfer/ExTransferable.Multi.html"><code>ExTransferable.Multi</code></a>

is a special transferable type used to transfer multiple objects (not
necessarily of the same type) at once. It only supports one, virtual
data flavor,

<a href="@org-openide-util-ui@/org/openide/util/datatransfer/ExTransferable.html#multiFlavor"><code>ExTransferable.multiFlavor</code></a>.

<p>The data associated with <code>multiFlavor</code> in the
<code>ExTransferable.Multi</code> will always be a special container
object,

<a href="@org-openide-util-ui@/org/openide/util/datatransfer/MultiTransferObject.html"><code>MultiTransferObject</code></a>.

It is designed to permit access to its constituent real
<code>Transferable</code>s.</p>

<div class="nonnormative">

<h2><a name="diagrams">UML Diagrams</a></h2>

<h3><a name="diagram_data_objects">Data objects</a></h3>

<img src="data_objects.gif" alt="DataObject UML">

<h3><a name="diagram_data_loaders">Data loaders</a></h3>

<img src="data_loaders.gif" alt="DataLoader UML">

</div>


<hr>@FOOTER@

</body>
</html>
